/**
  ******************************************************************************
  * @file           : SymmetricEncryption.cpp
  * @author         : sally
  * @brief          : None
  * @attention      : None
  * @date           : 24-11-11
  ******************************************************************************
  */
#include "SymmetricEncryption.h"

#include <cstddef>
#include <cstring>
#include <iostream>
#include <openssl/crypto.h>
#include <openssl/evp.h>
#include <openssl/rand.h>
#include <openssl/types.h>

namespace droneswarm
{
    SymmetricEncryption::SymmetricEncryption()
        : symmeticKey_((unsigned char*)OPENSSL_malloc(32))
          , iv_((unsigned char*)OPENSSL_malloc(16))
    {
    }

    SymmetricEncryption::~SymmetricEncryption()
    {
        OPENSSL_free(symmeticKey_);
        OPENSSL_free(iv_);
    }

    void SymmetricEncryption::setSymmeticKey(unsigned char* symmeticKey) { memcpy(symmeticKey_, symmeticKey, 32); }

    bool SymmetricEncryption::aes_Encryption(const unsigned char* plainText,
                                             int plainTextLen,
                                             unsigned char* cipherText,
                                             int* cipherTextLen)
    {
        int tmpLen = 0;
        //首先创建加密上下文
        EVP_CIPHER_CTX* ctx = EVP_CIPHER_CTX_new();

        //初始化加密参数
        if (!EVP_EncryptInit_ex2(ctx, EVP_aes_256_cbc(), symmeticKey_, iv_, nullptr))
        {
            std::cerr << "使用EVP_EncryptInit_ex2函数初始化加密参数失败" << std::endl;
            EVP_CIPHER_CTX_free(ctx);
            return false;
        }

        if (!EVP_EncryptUpdate(ctx, cipherText, cipherTextLen, plainText, plainTextLen))
        {
            std::cerr << "使用EVP_EncryptUpdate加密数据失败" << std::endl;
            EVP_CIPHER_CTX_free(ctx);
            return false;
        }

        if (!EVP_EncryptFinal_ex(ctx, cipherText + *cipherTextLen, &tmpLen))
        {
            std::cerr << "调用EVP_EncryptFinal加密数据失败" << std::endl;
            EVP_CIPHER_CTX_free(ctx);
            return false;
        }
        *cipherTextLen += tmpLen;
        // std::cout << "AES加密数据操作完成！" << std::endl;
        return true;
    }

    bool SymmetricEncryption::aes_Decryption(const unsigned char* cipherText,
                                             int cipherTextLen,
                                             unsigned char* plainText,
                                             int* plainTextLen)
    {
        EVP_CIPHER_CTX* ctx = EVP_CIPHER_CTX_new();

        if (!EVP_DecryptInit_ex2(ctx, EVP_aes_256_cbc(), symmeticKey_, iv_, nullptr))
        {
            std::cerr << "使用EVP_DecryptInit_ex2函数初始化加密参数失败" << std::endl;
            EVP_CIPHER_CTX_free(ctx);
            return false;
        }

        if (!EVP_DecryptUpdate(ctx, plainText, plainTextLen, cipherText, cipherTextLen))
        {
            std::cerr << "使用EVP_DecryptUpdate解密数据失败" << std::endl;
            EVP_CIPHER_CTX_free(ctx);
            return false;
        }

        int tmpLen = 0;

        if (!EVP_DecryptFinal_ex(ctx, plainText + *plainTextLen, &tmpLen))
        {
            std::cerr << "调用EVP_DecryptFinal解密数据失败" << std::endl;
            EVP_CIPHER_CTX_free(ctx);
            return false;
        }
        *plainTextLen += tmpLen;
        // std::cout << "AES解密数据操作完成！" << std::endl;
        return true;
    }
} // namespace droneswarm
